package org.testis.orm.refinedclasses;

import java.util.LinkedList;
import org.orm.PersistentException;
import java.util.HashMap;
import org.orm.PersistentTransaction;
import org.testis.orm.classes.T_bed_dut;
import org.testis.orm.classes.T_test_dataobject;
import org.testis.orm.classes.T_test_dataobjectCriteria;
import org.testis.orm.classes.T_test_designtree;
import org.testis.orm.classes.T_test_stepcontainer;
import org.testis.orm.classes.T_test_stepcontainerCriteria;
import org.testis.orm.classes.T_test_teststeps;
import org.testis.orm.classes.T_test_teststepsCriteria;
import org.testis.orm.manager.TestisDbPersistentManager;
import org.testis.orm.refinedclasses.TestDesignTreeRefined.TestDesignTreeParameters;
import org.testis.utils.middleware.TestDesign;
import org.testis.utils.tree.TreeNode;

/**
 * 
 * @author Cahit Emir Erel
 */
public class TestDesignTreeNode extends TreeNode implements Comparable {

    private TestDesignTreeRefined m_reference;
    private static HashMap<Integer, TestDesignTreeNode> m_nodeList = new HashMap<Integer, TestDesignTreeNode>();

    private TestDesignTreeNode() {
	super();
    }

    private TestDesignTreeNode(TestDesignTreeRefined reference,
	    DesignPart designpart) {
	this();
	m_reference = reference;
	setObject(designpart);
    }

    private TestDesignTreeNode(TestDesignTreeRefined reference) {
	super();
	m_reference = reference;
	DesignPart designpart = null;
	T_test_designtree dTree = reference.getTreeReference();
	String type = TestDesign.getDesignPartTypeName(dTree.getTypeId());
	try {
	    if (type.equals("TestSuite")) {
		designpart = new TestSuiteRefined(getStepContainer(dTree, type));
	    } else if (type.equals("TestPlan")) {
		designpart = new TestPlanRefined(getStepContainer(dTree, type));
	    } else if (type.equals("TestCaseGroup")) {
		designpart = new TestCaseGroupRefined(getStepContainer(dTree,
			type));
	    } else if (type.equals("TestCase")) {
		designpart = new TestCaseRefined(getStepContainer(dTree, type));
	    } else if (type.equals("TestStepGroup")) {
		designpart = new TestStepGroupRefined(getStepContainer(dTree,
			type));
	    } else if (type.equals("PreConditionCase")) {
		designpart = new PreConditionCaseRefined(getStepContainer(
			dTree, type));
	    } else if (type.equals("PostConditionCase")) {
		designpart = new PostConditionCaseRefined(getStepContainer(
			dTree, type));
	    } else if (type.equals("TestStep")) {
		designpart = new TestStepRefined(getStep(dTree));
	    } else if (type.equals("DataObject")) {
		designpart = new DataObjectRefined(getDataObject(dTree));
	    } else {
		throw new PersistentException();
	    }
	    setObject(designpart);
	} catch (PersistentException ex) {
	    ex.printStackTrace();
	}
    }

    public static TestDesignTreeNode createEmptyNode() {
	return new TestDesignTreeNode();
    }

    public static TestDesignTreeNode createNode(
	    TestDesignTreeRefined reference, DesignPart designpart) {
	return new TestDesignTreeNode(reference, designpart);
    }

    public static TestDesignTreeNode getNode(TestDesignTreeRefined reference,
	    DesignPart designpart) {
	if (m_nodeList.containsKey(reference.getId())) {
	    TestDesignTreeNode node = m_nodeList.get(reference.getId());
	    if (node.getObject().getId() != designpart.getId()) {
		node.setObject(designpart);
	    }
	    return node;
	}
	TestDesignTreeNode node = new TestDesignTreeNode(reference, designpart);
	m_nodeList.put(reference.getId(), node);
	return node;
    }

    public static TestDesignTreeNode getNode(TestDesignTreeRefined reference) {
	if (m_nodeList.containsKey(reference.getId())) {
	    TestDesignTreeNode node = m_nodeList.get(reference.getId());
	    return node;
	}
	TestDesignTreeNode node = new TestDesignTreeNode(reference);
	m_nodeList.put(reference.getId(), node);
	return node;
    }

    public static TestDesignTreeNode getNodeById(Integer id) {
	if (m_nodeList.containsKey(id)) {
	    TestDesignTreeNode node = m_nodeList.get(id);
	    return node;
	}
	return null;
    }

    public void addChild(TestDesignTreeNode node) {
	super.addChild(node);
	node.setParent(this);
    }

    public void addChild(int n, TestDesignTreeNode node) {
	super.addChild(n, node);
	node.setParent(this);
    }

    @Override
    public void setPlace(Integer place) {
	super.setPlace(place);
    }

    private T_test_stepcontainer getStepContainer(T_test_designtree reference,
	    String type) throws PersistentException {
	T_test_stepcontainerCriteria t_test_stepcontainerCriteria = new T_test_stepcontainerCriteria();
	t_test_stepcontainerCriteria.containerTypeId.eq(TestDesign
		.getDesignPartTypeIdByName(type));
	if (reference.getClone() != null) {
	    t_test_stepcontainerCriteria.id.eq(reference.getClone()
		    .getElementId());
	} else {
	    t_test_stepcontainerCriteria.id.eq(reference.getElementId());
	}
	return t_test_stepcontainerCriteria.uniqueT_test_stepcontainer();
    }

    private T_test_teststeps getStep(T_test_designtree reference)
	    throws PersistentException {
	T_test_teststepsCriteria t_test_teststepsCriteria = new T_test_teststepsCriteria();
	if (reference.getClone() != null) {
	    t_test_teststepsCriteria.id.eq(reference.getClone().getElementId());
	} else {
	    t_test_teststepsCriteria.id.eq(reference.getElementId());
	}
	return t_test_teststepsCriteria.uniqueT_test_teststeps();
    }

    private T_test_dataobject getDataObject(T_test_designtree reference)
	    throws PersistentException {
	T_test_dataobjectCriteria t_test_dataobjectCriteria = new T_test_dataobjectCriteria();
	if (reference.getClone() != null) {
	    t_test_dataobjectCriteria.id
		    .eq(reference.getClone().getElementId());
	} else {
	    t_test_dataobjectCriteria.id.eq(reference.getElementId());
	}
	return t_test_dataobjectCriteria.uniqueT_test_dataobject();
    }

    @Override
    public String getName() {
	try {
	    return getObject().getName();
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    @Override
    public TestDesignTreeNode getParent() {
	return (TestDesignTreeNode) super.getParent();
    }

    @Override
    synchronized protected void setObject(Object object) {
	if (object == null) {
	    throw new NullPointerException();
	}
	if (object instanceof DesignPart) {
	    super.setObject(object);
	} else {
	    throw new InstantiationError();
	}
    }

    synchronized public void setObject(DesignPart designPart) {
	super.setObject(designPart);
    }

    @Override
    public DesignPart getObject() {
	return (DesignPart) super.getObject();
    }

    synchronized private static TestDesignTreeRefined[] getClones(
	    TestDesignTreeRefined reference) {
	T_test_designtree treeRef = reference.getTreeReference();
	T_test_designtree[] clones;
	TestDesignTreeRefined[] cloneNodes;
	if (treeRef.t_test_designtree1 != null
		&& treeRef.t_test_designtree1.size() > 0) {
	    clones = treeRef.t_test_designtree1.toArray();
	} else {
	    clones = new T_test_designtree[0];
	}
	cloneNodes = new TestDesignTreeRefined[clones.length];
	for (int i = 0; i < cloneNodes.length; i++) {
	    cloneNodes[i] = TestDesignTreeRefined.getDesignTree(clones[i]);
	}
	return cloneNodes;
    }

    synchronized public TestDesignTreeRefined[] getClones() {
	return getClones(getReference());
    }

    synchronized private static int getNoOfClones(
	    TestDesignTreeRefined reference) {
	return getClones(reference).length;
    }

    synchronized private static boolean isSafeToDelete(
	    TestDesignTreeRefined reference, int safeThreshold) {
	if (safeThreshold < 0) {
	    safeThreshold = 0;
	}
	if (getNoOfClones(reference) <= safeThreshold) {
	    return true;
	} else {
	    return false;
	}
    }

    synchronized public boolean isSafeToDelete() {
	return isSafeToDelete(getReference(), 0);
    }

    synchronized public TestDesignTreeNode createRefinedDatabaseCopy(
	    TestDesignTreeRefined parentTreeNode, Integer previousTreeNode)
	    throws PersistentException {
	DesignPart objectCopy = getObject().createRefinedDatabaseCopy();
	int elementId = objectCopy.getId();
	if (elementId > 0) {
	    return getNode(
		    createDatabaseCopy(parentTreeNode, previousTreeNode,
			    elementId), objectCopy);
	} else {
	    throw new PersistentException(
		    "COPY FAILED! Element was not copied: " + getObject());
	}
    }

    synchronized public TestDesignTreeNode createRefinedDatabaseClone(
	    TestDesignTreeRefined parentTreeNode, Integer previousTreeNode)
	    throws PersistentException {
	DesignPart objectCopy = getObject().createRefinedDatabaseCopy();
	int elementId = objectCopy.getId();
	if (elementId > 0) {
	    return getNode(
		    createRefinedDatabaseClone(parentTreeNode,
			    previousTreeNode, elementId), objectCopy);
	} else {
	    throw new PersistentException(
		    "COPY FAILED! Element was not copied: " + getObject());
	}
    }

    synchronized private TestDesignTreeRefined createRefinedDatabaseClone(
	    TestDesignTreeRefined parent, Integer previousNodeId, int elementId)
	    throws PersistentException {
	T_test_designtree newTree = new T_test_designtree();
	newTree.save();
	TestDesignTreeRefined newNode = TestDesignTreeRefined
		.getDesignTree(newTree);

	newNode.getTreeReference().setElementId(elementId);
	newNode.getTreeReference().setRank(previousNodeId);
	newNode.getTreeReference().setParent(parent.getTreeReference());
	newNode.getTreeReference().setClone(null);
	newNode.getTreeReference().setTypeId(
		getReference().getTreeReference().getTypeId());

	newNode.setParameterValue(
		TestDesignTreeParameters.DeviceId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.DeviceId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.NicId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.NicId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.OwnerId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.OwnerId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.PcId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.PcId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.LanguageId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.LanguageId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.ProfileId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.ProfileId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.TestBedId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.TestBedId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.BrowserSpeed.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.BrowserSpeed.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.BrowserType.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.BrowserType.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.DeviceIp.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.DeviceIp.name()));

	if (newTree.save()) {
	    return newNode;
	} else {
	    throw new PersistentException(
		    "COPY FAILED! Design Tree was not copied: " + getName());
	}

    }

    synchronized private TestDesignTreeRefined createDatabaseCopy(
	    TestDesignTreeRefined parent, Integer previousNodeId, int elementId)
	    throws PersistentException {
	T_test_designtree newTree = new T_test_designtree();
	newTree.save();
	TestDesignTreeRefined newNode = TestDesignTreeRefined
		.getDesignTree(newTree);

	newNode.getTreeReference().setElementId(elementId);
	newNode.getTreeReference().setRank(previousNodeId);
	newNode.getTreeReference().setParent(parent.getTreeReference());
	newNode.getTreeReference().setClone(null);
	newNode.getTreeReference().setTypeId(
		getReference().getTreeReference().getTypeId());

	newNode.setParameterValue(
		TestDesignTreeParameters.DeviceId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.DeviceId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.ExpectedResultTypeId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.ExpectedResultTypeId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.NicId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.NicId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.OwnerId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.OwnerId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.PcId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.PcId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.LanguageId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.LanguageId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.ProfileId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.ProfileId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.TestBedId.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.TestBedId.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.AsynchCall.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.AsynchCall.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.BrowserSpeed.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.BrowserSpeed.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.BrowserType.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.BrowserType.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.Critical.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.Critical.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.DataArrayAppliestoCase.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.DataArrayAppliestoCase.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.DelayTime.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.DelayTime.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.DeviceIp.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.DeviceIp.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.InvocationCount.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.InvocationCount.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.NoOfRetryOnFail.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.NoOfRetryOnFail.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.RunAlways.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.RunAlways.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.SuccessPercentage.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.SuccessPercentage.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.ThreadPoolSize.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.ThreadPoolSize.name()));
	newNode.setParameterValue(
		TestDesignTreeParameters.Timeout.name(),
		getReference().getParameterValue(
			TestDesignTreeParameters.Timeout.name()));

	if (newTree.save()) {
	    return newNode;
	} else {
	    throw new PersistentException(
		    "COPY FAILED! Design Tree was not copied: " + getName());
	}

    }

    synchronized public void setDataFromOriginal(
	    TestDesignTreeRefined originalTree) {
	TestDesignTreeRefined originalNode = TestDesignTreeRefined
		.getDesignTree(getReference().getOriginalTreeReference());
	getReference().getTreeReference().setClone(null);
	getReference().setParameterValue(
		TestDesignTreeParameters.DeviceId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.DeviceId
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.ExpectedResultTypeId.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.ExpectedResultTypeId
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.NicId.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.NicId
			.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.OwnerId.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.OwnerId
			.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.PcId.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.PcId
			.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.LanguageId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.LanguageId
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.ProfileId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.ProfileId
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.TestBedId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.TestBedId
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.AsynchCall.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.AsynchCall
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.BrowserSpeed.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.BrowserSpeed
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.BrowserType.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.BrowserType
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.Critical.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.Critical
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.DataArrayAppliestoCase.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.DataArrayAppliestoCase
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.DelayTime.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.DelayTime
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.DeviceIp.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.DeviceIp
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.InvocationCount.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.InvocationCount
					.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.NoOfRetryOnFail.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.NoOfRetryOnFail
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.RunAlways.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.RunAlways
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.SuccessPercentage.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.SuccessPercentage
					.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.ThreadPoolSize.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.ThreadPoolSize
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.Timeout.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.Timeout
			.name()));
    }

    public boolean isGhost() {
	return isGhost(getReference());
    }

    public boolean isGhost(TestDesignTreeRefined node) {
	return node.isGhost();
    }

    public TestDesignTreeRefined makeOriginal() throws PersistentException {
	if (!isClone()) {
	    return null;
	}
	DesignPart part = getObject().createRefinedDatabaseCopy();
	PersistentTransaction t = TestisDbPersistentManager.instance()
		.getSession().beginTransaction();

	T_test_designtree original = getReference().getOriginalTreeReference();
	TestDesignTreeRefined originalNode = TestDesignTreeRefined
		.getDesignTree(original);
	getReference().getTreeReference().setElementId(part.getId());
	getReference().getTreeReference().setTypeId(
		originalNode.getTreeReference().getTypeId());

	getReference().setParameterValue(
		TestDesignTreeParameters.DeviceId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.DeviceId
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.ExpectedResultTypeId.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.ExpectedResultTypeId
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.NicId.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.NicId
			.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.OwnerId.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.OwnerId
			.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.PcId.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.PcId
			.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.LanguageId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.LanguageId
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.ProfileId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.ProfileId
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.TestBedId.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.TestBedId
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.AsynchCall.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.AsynchCall
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.BrowserSpeed.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.BrowserSpeed
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.BrowserType.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.BrowserType
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.Critical.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.Critical
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.DataArrayAppliestoCase.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.DataArrayAppliestoCase
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.DelayTime.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.DelayTime
				.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.DeviceIp.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.DeviceIp
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.InvocationCount.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.InvocationCount
					.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.NoOfRetryOnFail.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.NoOfRetryOnFail
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.RunAlways.name(),
		originalNode
			.getParameterValue(TestDesignTreeParameters.RunAlways
				.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.SuccessPercentage.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.SuccessPercentage
					.name()));
	getReference()
		.setParameterValue(
			TestDesignTreeParameters.ThreadPoolSize.name(),
			originalNode
				.getParameterValue(TestDesignTreeParameters.ThreadPoolSize
					.name()));
	getReference().setParameterValue(
		TestDesignTreeParameters.Timeout.name(),
		originalNode.getParameterValue(TestDesignTreeParameters.Timeout
			.name()));

	if (getReference().getTreeReference().save()) {
	    t.commit();
	    return getReference();
	} else {
	    t.rollback();
	    throw new PersistentException();
	}
    }

    public TestDesignTreeNode makeOriginalRefined() throws PersistentException {
	return getNode(makeOriginal());
    }

    @Override
    public Integer getPlace() {
	if (this.getParent() != null) {
	    return this.getParent().getChildIndex(this);
	} else {
	    return -1;
	}
	/* return super.getPlace(); */
    }

    public TestDesignTreeRefined getReference() {
	return m_reference;
    }

    @Override
    public TestDesignTreeNode getChild(int place) {
	return (TestDesignTreeNode) super.getChild(place);
    }

    public TestDesignTreeNode[] getChildrenForRun() {
	return super.getChildrenLinkedList().toArray(
		new TestDesignTreeNode[super.getChildrenLinkedList().size()]);
    }

    @Override
    public TestDesignTreeNode[] getChildren() {
	return super.getChildrenLinkedList().toArray(
		new TestDesignTreeNode[getChildrenLinkedList().size()]);
    }

    public LinkedList<TestDesignTreeNode> getChildrenAsList() {
	TestDesignTreeNode[] nodes = getChildren();
	LinkedList<TestDesignTreeNode> nodeList = new LinkedList<TestDesignTreeNode>();
	HashMap<Integer, String> map = new HashMap<Integer, String>();
	for (int i = 0; i < nodes.length; i++) {
	    TestDesignTreeRefined dtree = nodes[i].getReference();
	    if (!map.containsKey(dtree.getId())) {
		map.put(dtree.getId(), "");
		nodeList.add(getNode(dtree));
	    }
	}

	return nodeList;

    }

    public int getChildrenCount() {
	if (super.getChildrenLinkedList() == null) {
	    return 0;
	}
	return getChildrenAsList().size();
    }

    public void moveChild(int source, int target) {
	super.addChild(target, super.deleteChild(source));
    }

    @Override
    public LinkedList getChildrenLinkedList() {
	return super.getChildrenLinkedList();
    }

    @Override
    public String toString() {
	try {
	    StringBuffer buffer = new StringBuffer();
	    if (isClone()) {
		buffer.append("CLONE CLONE CLONE of Design Tree Id:"
			+ getReference().getTreeReference().getClone().getId());
	    } else {
		buffer.append("REAL");
	    }
	    buffer.append("\nDesign Tree Id: " + getId());
	    buffer.append("\n" + getObject().toString(this));
	    return buffer.toString();
	} catch (NullPointerException ex) {
	    return null;
	}
    }

    public int getId() {
	return getReference().getId();
    }

    private void handleNextSibling(TestDesignTreeNode nodeTodelete)
	    throws PersistentException {
	Integer previousNodeId = nodeTodelete.getReference().getTreeReference()
		.getRank();
	TestDesignTreeNode nextSibling = getNextSibling();
	if (nextSibling != null) { // If next node exists, the rank id is
				   // changed to
	    nextSibling.getReference().getTreeReference()
		    .setRank(previousNodeId);
	    if (!nextSibling.getReference().getTreeReference().save()) {
		throw new PersistentException();
	    }
	}
    }

    private boolean clearDelete(TestDesignTreeNode nodeTodelete)
	    throws PersistentException {
	boolean result = true;
	handleNextSibling(nodeTodelete);
	T_test_designtree original = null;
	if (isClone()) {
	    original = nodeTodelete.getReference().getTreeReference()
		    .getClone();
	    TestDesignTreeRefined refNode = TestDesignTreeRefined
		    .getDesignTree(original);
	    result = result
		    && nodeTodelete.getReference().getTreeReference()
			    .deleteAndDissociate();
	    if (isSafeToDelete(refNode, 0) && isGhost(refNode)) {

		result = result && original.deleteAndDissociate();
		result = result && nodeTodelete.getObject().delete();
	    } else {
		setObject(null);
	    }
	} else {
	    if (!nodeTodelete.isSafeToDelete()) {
		System.out.println("NOT SAFE to Delete! Converting to GHOST"
			+ nodeTodelete.getId());
		nodeTodelete.getReference().getTreeReference().setParent(null);
		nodeTodelete.getReference().getTreeReference().setRank(null);
	    } else {

		result = result
			&& nodeTodelete.getReference().getTreeReference()
				.deleteAndDissociate();
		result = result && nodeTodelete.getObject().delete();

	    }
	}
	if (result) {
	    if (nodeTodelete.getParent() != null) {
		nodeTodelete.getParent().deleteChild(nodeTodelete);
	    }
	    return true;
	} else {
	    return false;
	}
    }

    public boolean delete() {
	try {
	    if (clearDelete(this)) {
		return true;
	    }
	} catch (PersistentException ex) {
	    System.out
		    .println("name:" + this.getName() + " id:" + this.getId());
	    ex.printStackTrace();
	}

	return false;
    }

    public boolean isClone() {
	return getReference().isClone();
    }

    @Override
    public String getTypeName() {
	return getObject().getTypeName();
    }

    public TestDesignTreeNode getPrevSibling() {
	if (getParent() != null) {
	    return getParent().getPrevChild(this);
	} else {
	    return null;
	}
    }

    public TestDesignTreeNode getNextSibling() {
	if (getParent() != null) {
	    return getParent().getNextChild(this);
	} else {
	    return null;
	}
    }

    private TestDesignTreeNode getNextChild(TestDesignTreeNode child) {
	Integer spot = findChild(child);
	if (spot != null && spot + 1 < getChildrenLinkedList().size()) {
	    return (TestDesignTreeNode) getChildrenLinkedList().get(spot + 1);
	}
	return null;
    }

    private TestDesignTreeNode getPrevChild(TestDesignTreeNode child) {
	Integer spot = findChild(child);
	if (spot != null && spot - 1 >= 0) {
	    return (TestDesignTreeNode) getChildrenLinkedList().get(spot - 1);
	}
	return null;
    }

    synchronized public Integer findChild(TestDesignTreeNode child) {
	if (child != null) {
	    TestDesignTreeNode[] children = getChildren();
	    for (int i = 0; i < children.length; i++) {
		if (children[i].getId() == child.getId()) {
		    return i;
		}
	    }
	}
	return null;
    }

    private int compare(Comparable source) {
	TestDesignTreeNode src = (TestDesignTreeNode) source;
	if (!src.getName().equals(getName())) {
	    return Comparable.DIFFERENT_NAME;
	}
	if (!src.getTypeName().equals(getTypeName())) {
	    return Comparable.DIFFERENT_TYPE;
	}
	return getObject().compare(source, this);
    }

    @Override
    public int compare(Comparable source, Comparable treeReference) {
	return compare(source);
    }

    @Override
    public boolean compareParameters(HashMap<String, Object> params,
	    Comparable treeTreference) {
	String name = (String) params.get("name");
	if (!name.equals(getName())) {
	    return false;
	}
	return getObject().compareParameters(params, this);
    }

    public T_bed_dut getActiveDut() {
	T_bed_dut result = null;

	T_test_designtree temp = getReference().getTreeReference();
	do {
	    TestDesignTreeRefined ref = TestDesignTreeRefined
		    .getDesignTree(temp);
	    Integer deviceId = ref
		    .getParameterIntValue(TestDesignTreeParameters.DeviceId
			    .name());
	    if (deviceId != null) {
		result = TestDesign.getDutById(deviceId);
	    }
	    if (result != null) {
		break;
	    }
	    temp = temp.getParent();

	} while (temp != null && result == null);
	return result;
    }

    public String getTestStepModuleTypeName() {
	String result = null;
	T_test_designtree temp = getReference().getTreeReference();
	try {
	    do {
		if (TestDesign.getDesignPartTypeName(temp.getTypeId()).equals(
			"TestStep")) {
		    result = TestDesign.getModuleTypeName(getStep(temp)
			    .getModulTypeId());
		}
		temp = temp.getParent();
	    } while (temp != null && result == null);
	} catch (PersistentException ex) {
	}
	return result;
    }

    public String getTestStepActionName() {
	String result = null;
	T_test_designtree temp = getReference().getTreeReference();
	try {
	    do {
		if (TestDesign.getDesignPartTypeName(temp.getTypeId()).equals(
			"TestStep")) {
		    result = TestDesign.getActionTypeName(getStep(temp)
			    .getActionId());
		}
		temp = temp.getParent();
	    } while (temp != null && result == null);
	} catch (PersistentException ex) {
	}
	return result;
    }

    public String[] getKeys() {
	String[] result = null;
	T_test_designtree temp = getReference().getTreeReference();
	try {
	    do {
		if (TestDesign.getDesignPartTypeName(temp.getTypeId()).equals(
			"TestStep")) {
		    result = TestDesign.newInstance().getKeys(getStep(temp));
		}
		temp = temp.getParent();
	    } while (temp != null && result == null);
	} catch (PersistentException ex) {
	}
	return result;
    }

    public boolean hasSameRunTimeParams(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return getObject().hasSameRunTimeParams(params, this);
    }

    @Override
    public boolean isSelected() {
	return super.isSelected();
    }

    @Override
    protected int getChildIndex(TreeNode node) {
	int index = -1;
	TestDesignTreeNode dNode = (TestDesignTreeNode) node;
	for (int i = 0; i < getChildrenLinkedList().size(); i++) {
	    TestDesignTreeNode child = (TestDesignTreeNode) getChildrenLinkedList()
		    .get(i);
	    if (child.getId() == dNode.getId()) {
		index = i;
		break;
	    }
	}

	return index;
    }

    @Override
    protected boolean isContainsChild(TreeNode node) {
	boolean contains = false;

	TestDesignTreeNode dNode = (TestDesignTreeNode) node;

	for (int i = 0; i < getChildrenLinkedList().size(); i++) {
	    TestDesignTreeNode child = (TestDesignTreeNode) getChildrenLinkedList()
		    .get(i);
	    if (child.getId() == dNode.getId()) {
		contains = true;
		break;
	    }
	}

	return contains;

    }

    @Override
    public void deleteChild(TreeNode node) {
	if (node != null && node.getParent().equals(this)) {
	    TestDesignTreeNode dNode = (TestDesignTreeNode) node;
	    for (int i = 0; i < getChildrenLinkedList().size(); i++) {
		TestDesignTreeNode child = (TestDesignTreeNode) getChildrenLinkedList()
			.get(i);
		if (child.getId() == dNode.getId()) {
		    getChildrenLinkedList().remove(i);
		    break;
		}
	    }
	    node.setParent(null);
	}
    }
}
